﻿using System;
using System.Collections;
using System.Text;

namespace SpeakerRecognition
{
    /// <summary>
    /// 
    /// </summary>
    public class PrepareDataAndRunPAMCommand : ICommand
    {
        //************************  Private Fields  *******************************// 
        private ArrayList inputData;
        private ArrayList outputData;
        private double[,] distMat;
        private int numberOfMFCC = 16;
        private int maxNumberOfFrames;
        private bool withAC = false;
        private int numberOfCluster;
        private int minSize;
        private ArrayList inputToPAM;
        private DistanceMeasurement distanceType = DistanceMeasurement.EuclidianDistance;

        //************************  Public Properties  ****************************//

        public double[,] DistMat
        {
            get { return distMat; }
            set { distMat = value; }
        }

        public ArrayList InputToPAM
        {
            get { return inputToPAM; }
            set { inputToPAM = value; }
        }

        public DistanceMeasurement DistanceType
        {
            get { return distanceType; }
            set { distanceType = value; }
        }

        public ArrayList OutputData
        {
            get { return outputData; }
            set { outputData = value; }
        }

        public bool WithAC
        {
            get { return withAC; }
            set { withAC = value; }
        }

        public int NumberOfCluster
        {
            get { return numberOfCluster; }
            set { numberOfCluster = value; }
        }

        public int MaxNumberOfFrames
        {
            get { return maxNumberOfFrames; }
            set { maxNumberOfFrames = value; }
        }

        public int NumberOfMFCC
        {
            get { return numberOfMFCC; }
            set { numberOfMFCC = value; }
        }

        public ArrayList InputData
        {
            get { return inputData; }
            set { inputData = value; }
        }

        //************************  Public Methods  ****************************// 
        #region ICommand Members

        /// <summary>
        /// 
        /// </summary>
        public void execute()
        {
                // find the minimum number of frames to send to PAM
            findMin();

                // convert all double[][] arrays to one Dim double arrays with number of MFCC as set 
            createOneDimMFCCArray();
            outputData = PamClustering.execute(InputToPAM, numberOfCluster, DistanceType);
            DistMat = PamClustering.LastDisMatCalculated;
        }

        /// <summary>
        /// createWindowByType to get the MFCC only without PAM
        /// </summary>
        /// <returns></returns>
        public ArrayList convertTwoDImArraysToMFCC()
        {
            findMin();
            createOneDimMFCCArray();
            return InputToPAM;
        }

        private bool getHighFreq = false;

        public bool GetHighFreq
        {
            get { return getHighFreq; }
            set { getHighFreq = value; }
        }

        #endregion
        //************************  Private Methods  ****************************// 
        /// <summary>
        /// 
        /// </summary>
        private void findMin()
        {
            double[][] pointArray = (double[][])inputData[0];
            minSize = pointArray.Length;
            for (int i = 1; i < inputData.Count; i++)
            {
                pointArray = (double[][])inputData[i];
                if (pointArray.Length < minSize)
                    minSize = pointArray.Length;
            }
          
        }
        /// <summary>
        /// 
        /// </summary>
        private void createOneDimMFCCArray()
        {
            InputToPAM = new ArrayList();
            for (int m = 0; m < inputData.Count; m++)
            {
                double[] oneDimArray = new double[minSize * numberOfMFCC];
                double[][] pointArray = (double[][])inputData[m];
                // create an array for the output of MFCC
                for (int k = 0, i = 0; i < minSize; i++)
                {
                    int p = 1;
                    if (withAC)     // include the first MFCC in the array (power of frame)
                        p = 0;
                    if (!getHighFreq)
                        for (int j = p; j < numberOfMFCC + p; j++)
                        {
                            oneDimArray[k++] = pointArray[i][j];
                        }
                    else
                        for (int j = pointArray[i].Length - numberOfMFCC; j < pointArray[i].Length; j++)
                        {
                            oneDimArray[k++] = pointArray[i][j];
                        }
                }
                InputToPAM.Add(oneDimArray);
            }
        }


    }
}
